package demo.jackson;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;

import org.springframework.util.ReflectionUtils;

import java.io.IOException;
import java.util.HashSet;
import java.util.Set;

import lombok.Data;

/**
 * 动态序列化字段
 */
public class DynamicSerializer extends JsonSerializer<DynamicSerializer.Dynamic> {

    public static void main(String[] args) {
        ObjectMapper mapper = new ObjectMapper();
        try {
            A a = new A();
            a.age = 18;
            a.name = "zs";
            Set<String> keys = new HashSet<>();
            keys.add("name");
            a.setDynamic(keys);
            String value = mapper.writeValueAsString(a);
            System.out.println(value);
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public void serialize(Dynamic dynamic, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
        Set<String> keys = dynamic.getDynamic();
        keys.add("dynamic");
        jsonGenerator.writeStartObject();
        ReflectionUtils.doWithFields(dynamic.getClass(), field -> {
            field.setAccessible(true);
            Object value = field.get(dynamic);
            try {
                jsonGenerator.writeObjectField("key", value);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }, field -> !keys.contains(field.getName()));
        jsonGenerator.writeEndObject();
    }


    @JsonSerialize(using = DynamicSerializer.class)
    public interface Dynamic {
        Set<String> getDynamic();
    }

    @Data
    public static class A implements Dynamic {
        private String name;
        private int age;
        private Set<String> dynamic;
    }


}
